package com.s1.array;

/**
 * @author kai
 */
public class Array implements IList {

	protected static final int DEFAULT_LENGTH = 10;

	protected Integer[] datas;

	// 已使用的个数
	protected int used = 0;

	public Array() {
		this(DEFAULT_LENGTH);
	}

	public Array(int length) {
		super();
		this.datas = new Integer[length];
	}

	public Array(Integer[] datas) {
		super();
		this.datas = datas;
	}

	@Override
	public void print() {
		System.out.print("used / length : " + this.used + "/" + datas.length
				+ ", datas = [");
		for (int i = 0; i < datas.length; i++) {
			System.out.print(datas[i]);
			if (i != datas.length - 1) {
				System.out.print(", ");
			}
		}
		System.out.println("]");
	}

	/*
	 * 往尾部追加(添加)
	 */
	@Override
	public void add(Integer data) {
		this.addLast(data);
	}

	@Override
	public void addFirst(Integer data) {
		this.add(0, data);
	}

	@Override
	public void addLast(Integer data) {
		this.add(this.used, data);
	}

	/*
	 * 指定位置添加元素（有效范围内）
	 */
	@Override
	public void add(int position, Integer data) {
		if (position < 0 || position >= this.datas.length) {
			throw new RuntimeException("期望插入的位置" + position + "不在[0, "
					+ (this.datas.length - 1) + "]范围内");
		}

		if (used >= this.datas.length) {
			// 扩容
			this.expand(this.datas.length * 2);
		}
		for (int i = this.used - 1; i >= position; i--) {
			// [大 usedLength - 1, 小 position] -> [usedLength, position + 1]
			this.datas[i + 1] = this.datas[i];
		}
		this.datas[position] = data;
		this.used++;
	}

	@Override
	public Object remove() {
		return this.removeLast();
	}

	/*
	 * 删除首元素
	 */
	@Override
	public Object removeFirst() {
		return this.remove(0);
	}

	/*
	 * 删除尾元素
	 */
	@Override
	public Object removeLast() {
		return this.remove(this.used - 1);
	}

	/*
	 * 删除指定位置的元素
	 */
	@Override
	public Object remove(int position) {
		if (this.used <= 0) {
			throw new RuntimeException("数组已空下无法进行删除");
		}

		if (position < 0 || position >= this.datas.length) {
			throw new RuntimeException("数组不在范围内");
		}

		Object data = null;
		if (position < used) {
			// 原来下标为 position 的位置至 usedLength 往后移动一位
			for (int i = position; i <= used - 2; i++) {
				// [position, usedLength - 2] <- [小 position+1, 大 usedLength -
				// 1]
				this.datas[i] = this.datas[i + 1];
			}

			data = this.datas[used - 1];
			this.datas[used - 1] = null;
			this.used--;
		}
		return data;
	}

	@Override
	public Object remove(Object obj) {
		int index = this.findByData(obj);
		Object data = null;
		if (index != -1) {
			data = this.remove(index);
		}
		return data;
	}

	// 查1 ： 查询到具体元素
	public Integer findByPosition(int position) {
		return this.datas[position];
	}

	// 查2 ： 指定值找到下标，若查询不到则返回 -1
	public int findByData(Object data) {
		if (data != null) {
			for (int i = 0; i < this.datas.length; i++) {
				if (data.equals(this.datas[i])) {
					return i;
				}
			}
		}
		return -1;
	}

	/*
	 * 改1 ： 根据找到下标然后更改
	 */
	@Override
	public boolean updateByPosition(int position, Integer value) {
		this.datas[position] = value;
		return true;
	}

	/*
	 * 改2 ： 就是找到下标，然后更改
	 */
	@Override
	public boolean updateByData(Integer oldData, Integer newData) {
		int pos = this.findByData(oldData);
		if (pos != -1) {
			updateByPosition(pos, newData);
			return true;
		}
		return false;
	}

	// 扩容
	public void expand(int length) {
		Integer[] newDatas = new Integer[length];
		// 数据搬移
		for (int i = 0; i < this.datas.length; i++) {
			newDatas[i] = this.datas[i];
		}
		this.datas = newDatas;
	}

	// 数组合并
	public IList merge(Array otherArray) {
		int newLength = this.datas.length + otherArray.datas.length;
		Integer[] newDatas = new Integer[newLength];

		int i;
		for (i = 0; i < this.used; i++) {
			newDatas[i] = this.datas[i];
		}
		for (i = 0; i < otherArray.used; i++) {
			newDatas[i + this.used] = otherArray.datas[i];
		}

		this.datas = newDatas;
		this.used += otherArray.used;
		return otherArray;
	}

	@Override
	public void clear() {
		for (int i = this.datas.length - 1; i >= 0; i--) {
			this.datas[i] = null;
		}
		this.used = 0;
	}

}
